<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app"></div>
    <script>
      // 定义一个副作用函数桶
      const bucket = new Set();

      function isObject(value) {
        return typeof value === "object" && value !== null;
      }

      function reactive(data) {
        if (!isObject) return;

        return new Proxy(data, {
          get(target, key) {
            return target[key];
          },
          set(target, key, value) {
            target[key] = value;
            // 调用副作用函数
            bucket.forEach((fn) => fn());
            return true;
          },
        });
      }
      const state = { name: "孙悟空", age: 18 };
      // 定义一个变量，触发者
      const proxy = reactive(state);

      // 定义一个函数，响应者
      function effect() {
        app.innerHTML = proxy.name;
      }
      effect();
      // 放入桶中 多次添加也只会存在一个
      bucket.add(effect);
      bucket.add(effect);
      function effect1() {
        console.log('effect1被执行了...')
      }
      // 放入桶中
      bucket.add(effect1);
      // 模拟数据的改变
      setTimeout(() => {
        proxy.name = "猪八戒";
      }, 1000);

      /*
       问题：当所有的副作用都在一个桶内时，只修改name属性，会导致effct1也触发，从而改变age属性
        应该如何处理？
        修改某个属性时，应该只触发与之对应的副作用函数，其他属性的副作用函数不应该触发！

        解决方式：建立一个映射关系，属性名---对应该属性的副作用函数

        由此又引来一个新的问题：依赖收集(那些副作用函数引用了属性1，哪些引用了属性2，哪些引用了属性3...)

        思路：
          1. 将当前副作用函数保存到一个全局变量
          2. 当执行副作用函数时，会触发代理对象的get操作，此时可以获取到key,也就是属性名
          3. 将全局变量中保存的副作用函数，添加到对应的桶内
      */
    </script>
  </body>
</html>
